<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
</body>
</html>

<script>
// 面向对象的十二字箴言：
  // 高内聚、低耦合     ->  目的：为了让 对象(构造函数)，能抽到 单独的文件当中，以供 “代码「复用」”
  // 封装、继承    ->  目的：代码的「复用性」
  // 多态
// 代码复用性是什么思想的践行：DRY  ->  Don't Repect Yourself。
  // 即，但凡代码重复了，就要将 重复的代码，提取成共用的一份；为了 代码的复用性。


// ------------  思考：如何将代码的 Teacher  和 Student 重复的代码，提取；以 践行 DRY.

// 哪些代码能提取：
  // 1. 实例方法（在原型对象上） 可以提取成一份： sayHi    ...
  // 2. 实例属性（在对象内部） name 、 height 、 weight  ...

// const obj  = { xx: 'xx' }
function Teacher(major, name, height, weight) {
  // this.objg = obj; // obj 为全局变量的 obj， 即 Teacher 和全局作用域 耦合
  this.major = major;
  this.name = name;
  this.height = height;
  this.weight = weight;
}

// 往Teacher 中，增加 实例方法
// Teacher.prototype.sayHi = function() {
//   console.log(`你好呀, 我叫 ${this.name}`);
// }


function Student(level, name, height, weight) {
  this.level = level;
  this.name = name;
  this.height = height;
  this.weight = weight;
}

// 往 Student 中，增加 实例方法
// Student.prototype.sayHi = function() {
//   console.log(`你好呀，我叫${this.name}`);
// }


// 面向对象上的 实例属性，如何 继承/共用/共享：
// 思想：Student 和 Teacher 都叫 类，他们是一个“维度的”；比这个维度更高，可以有 Person 类

// 管 Person 类，叫 “父类”； 管 Student 和 Teacher 叫 “子类”；
function Person() {}

// 用子类「继承」父类的 方法
Person.prototype.sayHi = function() {
  console.log(`你好呀，我叫${this.name}`);
}

// 管这种继承的形式，叫原型继承
Student.prototype = new Person('老师');
// Student.prototype.constructor  ->  没这个属性 了
Student.prototype.constructor = Student; // ** !! 通过原型继承，必须 重新改变 原型对象 constructor 重新 指向 自己的构造函数


Teacher.prototype = new Person();
Teacher.prototype.constructor = Teacher;

const xiaoming  = new Student('3年级', '小米', '150cm', '50kg');
const laozhang = new Teacher('数学', '老张', '180cm', '70kg');

// xiaoming.__proto__  指向 Student.prototype
// xiaoming.__proto__.__proto__  指向 Person.prototype
// xiaoming.__proto__.__proto__.__proto__ 指向 Object.prototype

console.log(xiaoming);



// 总结：原型继承
// 作用：实现了  不能 类的实例对象，共用 父类的 实例方法；
  // 从而实现，不用 子类，都能 复用 父类的 实例方法
// 缺点：不同 子类 中 属性，还没做到 DRY。
</script>